package com.mdd.front.service.order.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.google.common.collect.Lists;
import com.mdd.common.config.AlipayConfig;
import com.mdd.common.constant.GlobalConstant;
import com.mdd.common.core.PageResult;
import com.mdd.common.dto.OrderDto;
import com.mdd.common.dto.result.OrderPageResultDto;
import com.mdd.common.entity.account.AccountLog;
import com.mdd.common.entity.address.UserAddress;
import com.mdd.common.entity.album.Album;
import com.mdd.common.entity.coupon.Coupon;
import com.mdd.common.entity.coupon.UserCoupon;
import com.mdd.common.entity.goods.*;
import com.mdd.common.entity.log.OrderLog;
import com.mdd.common.entity.log.OrderRefundLog;
import com.mdd.common.entity.order.Order;
import com.mdd.common.entity.recharge.RechargeOrder;
import com.mdd.common.entity.refund.OrderRefund;
import com.mdd.common.entity.relevancy.OrderBuyRelevancy;
import com.mdd.common.entity.salesman.Salesman;
import com.mdd.common.entity.salesman.SalesmanGoogs;
import com.mdd.common.entity.salesman.UserSalesman;
import com.mdd.common.entity.staff.Staff;
import com.mdd.common.entity.user.User;
import com.mdd.common.enums.*;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.account.AccountLogMapper;
import com.mdd.common.mapper.address.UserAddressMapper;
import com.mdd.common.mapper.coupon.CouponMapper;
import com.mdd.common.mapper.coupon.UserCouponMapper;
import com.mdd.common.mapper.goods.GoodsMapper;
import com.mdd.common.mapper.goods.OrderGoodsMapper;
import com.mdd.common.mapper.googs.SalesmanGoogsMapper;
import com.mdd.common.mapper.order.OrderMapper;
import com.mdd.common.mapper.recharge.RechargeOrderMapper;
import com.mdd.common.mapper.refund.OrderRefundMapper;
import com.mdd.common.mapper.relevancy.OrderBuyRelevancyMapper;
import com.mdd.common.mapper.salesman.SalesmanMapper;
import com.mdd.common.mapper.specification.GoodsSpecificationMapper;
import com.mdd.common.mapper.unit.GoodsUnitMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.plugin.notice.NoticeDriver;
import com.mdd.common.plugin.storage.StorageDriver;
import com.mdd.common.utils.*;
import com.mdd.common.utils.phone.AliPhoneUtil;
import com.mdd.front.LikeFrontThreadLocal;
import com.mdd.front.service.album.IAlbumService;
import com.mdd.front.service.comment.IGoodsCommentService;
import com.mdd.front.service.goods.IGoodsService;
import com.mdd.front.service.goods.IOrderGoodsService;
import com.mdd.front.service.log.IOrderLogService;
import com.mdd.front.service.log.IOrderRefundLogService;
import com.mdd.front.service.order.IOrderService;
import com.mdd.front.service.pay.ICBCService;
import com.mdd.front.service.recharge.IRechargeService;
import com.mdd.front.service.refund.IOrderRefundService;
import com.mdd.front.service.region.IDevRegionService;
import com.mdd.front.service.salesman.IUserSalesmanService;
import com.mdd.front.service.specification.impl.GoodsSpecificationServiceImpl;
import com.mdd.front.service.staff.IStaffService;
import com.mdd.front.validate.PageParam;
import com.mdd.front.validate.order.OrderParam;
import com.mdd.front.validate.refund.OrderRefundParam;
import com.mdd.front.vo.goods.OrderGoodsDetailVo;
import com.mdd.front.vo.order.OrderDetailVo;
import com.mdd.front.vo.order.OrderListVo;
import com.mdd.front.vo.specification.GoodsSpecificationDetailVo;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * 订单实现类
 */
@Log4j2
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

	@Resource
	OrderMapper orderMapper;
	@Resource
	OrderGoodsMapper orderGoodsMapper;

	@Resource
	private UserMapper userMapper;
	@Resource
	private AccountLogMapper accountLogMapper;

	@Resource
	private IOrderGoodsService orderGoodsService;

	@Resource
	private IStaffService staffService;

	@Resource
	private IGoodsService goodsService;
	@Resource
	private GoodsSpecificationServiceImpl goodsSpecificationServiceImpl;

	@Resource
	private GoodsUnitMapper unitMapper;

	@Resource
	private IOrderLogService orderLogService;

	@Resource
	private IAlbumService iAlbumService;

	@Resource
	private IOrderRefundService orderRefundService;

	@Resource
	private IDevRegionService regionService;

	@Resource
	private UserAddressMapper addressMapper;

	@Value("${wx.app.appId}")
	private String appId;

	@Value("${wx.app.secret}")
	private String appSecret;

	@Resource
	private IGoodsCommentService goodsCommentService;

	@Resource
	private IOrderRefundLogService orderRefundLogService;

	@Resource
	private OrderRefundMapper orderRefundMapper;

	@Value("${wx.pay.order-refund-notify-url}")
	private String orderRefundNotifyUrl;
	@Resource
	private RechargeOrderMapper rechargeOrderMapper;
	@Resource
	private IRechargeService iRechargeService;

	@Resource
	private ICBCService iCBCService;
	@Resource
	private RestTemplate restTemplate;

	@Resource(name = "taskExecutor")
	private Executor executor;

	@Value("${enable.VerificationCode:false}")
	private boolean isEnableCode;

	@Value("${wx.qr.generationUrl}")
	private String url;

	@Value("${wx.qr.envProfile}")
	private String envProfile;

	@Value("${wx.qr.accessToken}")
	private String accessTokenUrl;

	@Resource
	private IUserSalesmanService userSalesmanService;
	@Resource
	private SalesmanGoogsMapper salesmanGoogsMapper;

	@Resource
	private SalesmanMapper salesmanMapper;

	@Resource
	private GoodsSpecificationMapper goodsSpecificationMapper;

	@Resource
	private CouponMapper couponMapper;

	@Resource
	private OrderBuyRelevancyMapper orderBuyRelevancyMapper;
	@Resource
	private GoodsMapper goodsMapper;
	@Qualifier("userCouponMapper")
	@Resource
	private UserCouponMapper userCouponMapper;

	/**
	 * 订单列表
	 *
	 * @param pageParam 分页参数
	 * @param params    搜索参数
	 * @return PageResult<OrderListVo>
	 */
	@Override
	public PageResult<OrderListVo> list(PageParam pageParam, Map<String, String> params) {
		Integer pageNo = pageParam.getPageNo();
		Integer pageSize = pageParam.getPageSize();
		LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
		Long userId = StringUtils.isEmpty(params.get("userId")) ? null : Long.valueOf(params.get("userId"));
		Long orderStatus = StringUtils.isEmpty(params.get("orderStatus")) ? null : Long.valueOf(params.get("orderStatus"));
		Long orderType = StringUtils.isEmpty(params.get("orderType")) ? null : Long.valueOf(params.get("orderType"));
		queryWrapper.eq(userId != null, Order::getUserId, userId);
		queryWrapper.eq(orderStatus != null, Order::getOrderStatus, orderStatus);
		queryWrapper.eq(orderType != null, Order::getOrderType, orderType);
		queryWrapper.eq(Order::getIsDelete, GlobalConstant.NOT_DELETE);
		queryWrapper.orderByDesc(Order::getId);
		return commonPage(pageNo, pageSize, null, queryWrapper);
	}

	/**
	 * 订单列表
	 *
	 * @param pageParam 分页参数
	 * @param params    搜索参数
	 * @return PageResult<OrderListVo>
	 */
	@Override
	public PageResult<OrderListVo> listSalesman(PageParam pageParam, Map<String, Object> params) {
		Integer pageNo = pageParam.getPageNo();
		Integer pageSize = pageParam.getPageSize();
		LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Order::getIsDelete, GlobalConstant.NOT_DELETE);
		queryWrapper.eq(Order::getSalesmanUserId, params.get("user_id"));
		queryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.FINISHED.getStatus());
		queryWrapper.orderByDesc(Order::getId);
		return commonPage(pageNo, pageSize, null, queryWrapper);
	}

	private PageResult<OrderListVo> commonPage(Integer pageNo, Integer pageSize, Staff staff, LambdaQueryWrapper<Order> queryWrapper) {
		IPage<Order> iPage = orderMapper.selectPage(new Page<>(pageNo, pageSize), queryWrapper);

		if (iPage == null || CollectionUtils.isEmpty(iPage.getRecords())) {
			return PageResult.iPageHandle(0L, iPage.getCurrent(), iPage.getSize(), Lists.newArrayList());
		}
		List<Order> records = iPage.getRecords();
		List<Long> orderIds = records.stream().map(Order::getId).distinct().collect(Collectors.toList());
		List<OrderGoodsDetailVo> orderGoodsList = orderGoodsService.listByOrderIds(orderIds);
		Map<Long, OrderGoodsDetailVo> map = orderGoodsList.stream().collect(Collectors.toMap(OrderGoodsDetailVo::getOrderId, item -> item, (a, b) -> b));
		List<Long> goodsIds = orderGoodsList.stream().map(OrderGoodsDetailVo::getGoodsId).distinct().collect(Collectors.toList());
		Map<Long, String> goodsImageMap = goodsService.listByIds(goodsIds).stream().collect(Collectors.toMap(item -> item.getId(), item -> item.getImage()));
		List<OrderListVo> list = new LinkedList<>();
		Map<Integer, String> dispatchMap = OrderDispatchEnum.getMap();
		Map<Integer, String> orderStatusMap = OrderStatusEnum.getMap();

		Map<String, String> transactionSettingMap = ConfigUtil.get(GlobalConstant.TRANSACTION_SETTING);
		String cancelUpdateOrders = transactionSettingMap.get(GlobalConstant.CANCEL_UNPAID_ORDERS);
		String cancelUpdateOrdersTime = transactionSettingMap.get(GlobalConstant.CANCEL_UNPAID_ORDERS_TIMES);
		List<GoodsComment> commentList = goodsCommentService.listByOrderIds(orderIds);
		List<Long> commentOrderIds = Lists.newArrayList();
		if (CollectionUtils.isNotEmpty(commentList)) {
			commentOrderIds = commentList.stream().map(GoodsComment::getOrderGoodsId).distinct().collect(Collectors.toList());
		}
		List<Order> updateOrder = new ArrayList<>();
		for (Order item : records) {
			UserAddress userAddress = addressMapper.selectOne(new LambdaQueryWrapper<UserAddress>().eq(UserAddress::getUserId,LikeFrontThreadLocal.getUserId()));
			OrderListVo vo = new OrderListVo();
			BeanUtils.copyProperties(item, vo);
			OrderGoodsDetailVo detailVo = map.get(item.getId());
			if (null != detailVo) {
				detailVo.setImageUrl(UrlUtil.toAbsoluteUrl(goodsImageMap.get(detailVo.getGoodsId())));
			}
			if (staff != null) {
				if (OrderStatusEnum.RESERVE.getStatus() == item.getOrderStatus()) {
					vo.setServiceBtn(1);
				} else if (OrderStatusEnum.SERVICING.getStatus() == item.getOrderStatus()) {
					vo.setVerificationBtn(1);
				}
			} else {
				if (OrderStatusEnum.WAIT_PAY.getStatus() == item.getOrderStatus()) {
					vo.setPayBtn(1);
					vo.setCancelBtn(1);
					LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(item.getCreateTime()), ZoneOffset.of("+8"));
					LocalDateTime time = localDateTime.plusMinutes(Long.parseLong(cancelUpdateOrdersTime));
					long cancelBtnTime = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000;
					vo.setCancelBtnTime("1".equals(cancelUpdateOrders) ? cancelBtnTime : null);
				} else if (OrderStatusEnum.RESERVE.getStatus() == item.getOrderStatus()) {
					vo.setCancelBtn(1);
				} else if (OrderStatusEnum.FINISHED.getStatus() == item.getOrderStatus()) {
					if (!commentOrderIds.contains(item.getId())) {
						vo.setCommentBtn(1);
					}
					vo.setContactBtn(1);
				} else if (OrderStatusEnum.CLOSE.getStatus() == item.getOrderStatus()) {
					vo.setDelBtn(1);
				}
			}
			vo.setAddressId(userAddress.getId());
			vo.setOrderGoodsDetailVo(detailVo);
			vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
			vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
			vo.setIsDispatchName(dispatchMap.get(item.getIsDispatch()));
			vo.setOrderStatusName(orderStatusMap.get(item.getOrderStatus()));
			vo.setAppointTimeStart(TimeUtil.getHourMinute(item.getAppointTimeStart()));
			vo.setAppointTimeEnd(TimeUtil.getHourMinute(item.getAppointTimeEnd()));
			vo.setWeekDay(TimeUtil.getWeekDay(item.getAppointTimeStart()));
			vo.setAppointTime(TimeUtil.timestampToDate(item.getAppointTimeStart(), "yyyy-MM-dd"));
			if ((System.currentTimeMillis() / 1000) > item.getCancelTime() && item.getOrderStatus().equals(OrderStatusEnum.WAIT_PAY.getStatus())) {
				updateOrder.add(item);
				vo.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
			}
			if (vo.getOrderStatus().equals(OrderStatusEnum.RESERVE.getStatus()) && vo.getIsDispatch().equals(1)) {
				vo.setOrderStatus(OrderStatusEnum.DISPATCHING.getStatus());
				vo.setOrderStatusName("派单中");
			}
			if (vo.getPayStatus()==0 && vo.getOrderStatus() == 6){
				vo.setOrderStatus(0);
				item.setOrderStatus(0);
				orderMapper.updateById(item);
			}
			list.add(vo);
		}
		if (Objects.nonNull(updateOrder)) {
			executor.execute(new Runnable() {
				@Override
				public void run() {
					updateOrder.forEach(order -> {
						order.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
						orderMapper.updateById(order);
					});
				}
			});
		}

		return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
	}

	@Override
	public PageResult<OrderListVo> staffOrderList(PageParam pageParam, Map<String, String> params) {
		Integer pageNo = pageParam.getPageNo();
		Integer pageSize = pageParam.getPageSize();
		Long userId = Long.valueOf(params.get("userId"));
		Integer orderStatus = null;
		List<Integer> orderStatusList = Lists.newArrayList();
		if (StringUtils.isNotEmpty(params.get("orderStatus"))) {
			orderStatus = Integer.valueOf(params.get("orderStatus"));
		} else {
			orderStatusList = Arrays.asList(OrderStatusEnum.SERVICING.getStatus(), OrderStatusEnum.RESERVE.getStatus(), OrderStatusEnum.FINISHED.getStatus());
		}
		Staff staff = staffService.getByUserId(userId);
		LambdaQueryWrapper<Order> queryWrapper;
		if (staff == null) {
			throw new OperateException("当前用户不是师傅");
		} else {
			// 当前师傅只能看到服务范围内的订单数据
			queryWrapper = new LambdaQueryWrapper<Order>()
//                    .eq(staff != null, Order::getStaffId, staff.getId())
					.eq(Order::getIsDelete, GlobalConstant.NOT_DELETE)
					.eq(orderStatus != null, Order::getOrderStatus, orderStatus)
					.apply("FIND_IN_SET(" + staff.getId() + ", `staff_ids`)")
					.in(CollectionUtils.isNotEmpty(orderStatusList), Order::getOrderStatus, orderStatusList)
					.orderByDesc(Order::getId);
		}
		return this.commonPage(pageNo, pageSize, staff, queryWrapper);
	}

    /**
     * 订单详情
     *
     * @param id 主键参数
     * @return Order
     */
    @Override
    public OrderDetailVo detail(Integer id) {
        Order model = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("id", id)
                        .last("limit 1"));
        Assert.notNull(model, "数据不存在");
        Map<Long, String> regionMap = regionService.getRegionMap();
        OrderDetailVo vo = new OrderDetailVo();
        BeanUtils.copyProperties(model, vo);
		UserAddress userAddressOrder = addressMapper.selectOne(new LambdaQueryWrapper<UserAddress>().eq(UserAddress::getUserId,model.getUserId()));
		vo.setAddressId(userAddressOrder.getId());
		vo.setIsBuy(model.getIsBuy());
        vo.setOrderTerminalName(ClientEnum.getMsgByCode(model.getOrderTerminal()));
        vo.setOrderTypeName(OrderTypeEnum.getMap().get(model.getOrderType()));
        vo.setPayStatusName(OrderPayStatusEnum.getMap().get(model.getPayStatus()));
        vo.setPayWayName(OrderPlayTypeEnum.getMap().get(model.getPayWay()));
        vo.setVerificationStatusName(OrderVerificationStatusEnum.getMap().get(model.getVerificationStatus()));
        vo.setIsDispatchName(OrderDispatchEnum.getMap().get(model.getIsDispatch()));
        vo.setOrderStatusName(OrderStatusEnum.getMap().get(model.getOrderStatus()));
        vo.setProvince(regionMap.get(model.getProvinceId()));
        vo.setCity(regionMap.get(model.getCityId()));
        vo.setDistrict(regionMap.get(model.getDistrictId()));
        vo.setWeekDay(TimeUtil.getWeekDay(model.getAppointTimeStart()));
        vo.setAppointTime(TimeUtil.timestampToDate(model.getAppointTimeStart(), "yyyy-MM-dd"));
        vo.setCreateTime(TimeUtil.timestampToDate(model.getCreateTime()));
        vo.setAppointTimeStartStr(TimeUtil.getHourMinute(model.getAppointTimeStart()));
        vo.setAppointTimeEndStr(TimeUtil.getHourMinute(model.getAppointTimeEnd()));
        vo.setFinishTime(TimeUtil.timestampToDate(model.getFinishTime()));
        vo.setCancelTime(TimeUtil.timestampToDate(model.getCancelTime()));
        OrderGoods orderGoods = orderGoodsService.getByOrderId(vo.getId());

		GoodsComment goodsComment = goodsCommentService.listByOrderId(model.getId());
		if (orderGoods != null) {
			OrderGoodsDetailVo detailVo = new OrderGoodsDetailVo();
			BeanUtils.copyProperties(orderGoods, detailVo);
			Goods goods = goodsService.getEntityById(detailVo.getGoodsId());
			detailVo.setImageUrl(UrlUtil.toAbsoluteUrl(goods.getImage()));
			vo.setOrderGoods(detailVo);
		}
		if (vo.getStaffIds() != null) {
			List<String> list = Arrays.asList(vo.getStaffIds().split(","));
			ArrayList<Integer> integers = new ArrayList<>();
			list.forEach(l -> integers.add(Integer.valueOf(l)));
			List<Staff> staff = staffService.listByIds(integers);
			vo.setStaff(staff);
		}
		// 当前用户是否为师傅
		if (OrderStatusEnum.SERVICING.getStatus() == model.getOrderStatus()) {
			vo.setContactBtn(1);
			vo.setVerificationBtn(1);
		} else if (OrderStatusEnum.WAIT_PAY.getStatus() == model.getOrderStatus()) {
			vo.setPayBtn(1);
		} else if (OrderStatusEnum.RESERVE.getStatus() == model.getOrderStatus()) {
			vo.setCancelBtn(1);
			vo.setServiceBtn(1);
		} else if (OrderStatusEnum.FINISHED.getStatus() == model.getOrderStatus()) {
			if (goodsComment == null) {
				vo.setCommentBtn(1);
			}
		} else if (OrderStatusEnum.CLOSE.getStatus() == model.getOrderStatus()) {
			vo.setDelBtn(1);
		}
		// 设置订单的经纬度
		HashMap<String, Object> hashMap = new HashMap<>();
		hashMap.put("province_id", model.getProvinceId());
		hashMap.put("city_id", model.getCityId());
		hashMap.put("district_id", model.getDistrictId());
		hashMap.put("address", model.getAddress());
		List<UserAddress> userAddresses = addressMapper.selectByMap(hashMap);
		for (UserAddress userAddress : userAddresses) {
			if (StringUtil.isNotEmpty(userAddress.getLongitude()) && StringUtil.isNotEmpty(userAddress.getLatitude())) {
				vo.setLongitude(userAddress.getLongitude());
				vo.setLatitude(userAddress.getLatitude());
				vo.setAddressId(userAddress.getId());
				break;
			}
		}
		GoodsSpecification goodsSpecificationId = goodsSpecificationMapper.selectOne(new QueryWrapper<GoodsSpecification>().eq("goods_specification_id", orderGoods.getGoodsId()));
		GoodsSpecificationDetailVo goodsSpecificationDetailVo = new GoodsSpecificationDetailVo();
		if(Objects.nonNull(goodsSpecificationId)) {
			BeanUtils.copyProperties(goodsSpecificationDetailVo,goodsSpecificationId);
		}
		vo.setSpecificationDetailVo(goodsSpecificationDetailVo);

		//部分退款
		OrderRefund orderRefund = orderRefundMapper.selectOne(new QueryWrapper<OrderRefund>().eq("order_id", id).last("limit 1"));
		if(Objects.nonNull(orderRefund)){
			vo.setReviewStatus(orderRefund.getReviewStatus());
		}

		vo.setGoodsHostId(orderGoods.getGoodsId().intValue());
		return vo;
	}

	/**
	 * 订单新增
	 *
	 * @param orderParam 参数
	 */
	@Override
	@Transactional
	public Order add(OrderParam orderParam) {
		Order model = new Order();
		// 订单编号
		model.setSn(SnUtils.getOrderSn());
		model.setUserId(orderParam.getUserId());
		// 第三方交易流水
		//model.setTransactionId(orderParam.getTransactio);
		// 选择师傅
		Staff staff = this.getRandomStaff(orderParam);
		if (null != staff) {
			model.setStaffId(staff.getId());
		}
		model.setIsDispatch(OrderDispatchEnum.NOT_DISPATCH.getStatus());
		model.setOrderType(orderParam.getOrderType());
		// 默认小程序
		model.setOrderTerminal(orderParam.getOrderTerminal());
		Integer orderStatus = orderParam.getOrderStatus();
		model.setOrderStatus(ObjectUtils.isNotEmpty(orderStatus) ? orderStatus:OrderStatusEnum.WAIT_PAY.getStatus());
		model.setPayStatus(OrderPayStatusEnum.WAIT_PAY.getStatus());
		// v1.0版本默认微信支付
		model.setPayWay(PaymentEnum.UN_PAID.getCode());
		model.setUserRemark(orderParam.getUserRemark());
		model.setOrderRemarks(orderParam.getOrderRemarks());
		//model.setVerificationCode(orderParam.getVerificationCode());
		// 默认未核销
		model.setVerificationStatus(OrderVerificationStatusEnum.WAIT_VERIFICATION.getStatus());

		// 获取地址
		UserAddress userAddress = addressMapper.selectById(orderParam.getAddressId());
		Assert.notNull(userAddress, "用户收获地址不能为空");
		model.setContact(userAddress.getContact());
		model.setMobile(userAddress.getMobile());
		model.setProvinceId(userAddress.getProvinceId());
		model.setCityId(userAddress.getCityId());
		model.setDistrictId(userAddress.getDistrictId());
		model.setAddress(userAddress.getAddress());

		// 服务信息
		Goods goods = goodsSpecificationServiceImpl.getGoodsBySpecificationId(orderParam.getGoodsId(), Long.valueOf(orderParam.getIsBuy()));
		Integer orderNum = orderParam.getTotalNum() == null ? 0 : orderParam.getTotalNum();
		orderNum = orderNum + goods.getOrderNum();
		goods.setOrderNum(orderNum);
		goodsService.updateEntityById(goods);

		Assert.notNull(goods, "服务信息不能为空");
		model.setGoodsPrice(goods.getPrice());

		GoodsUnit goodsUnit = unitMapper.selectById(goods.getUnitId());
		Assert.notNull(goodsUnit, "单位信息不能为空");
		//获取订单取消时间
		Map<String, String> config = ConfigUtil.get("transaction");
		String cancelUnpaidOrdersTimes = config.getOrDefault("cancel_unpaid_orders_times", TimeUtil.timestamp() + "");
		model.setTotalNum(orderParam.getTotalNum());
		model.setAppointTimeStart(orderParam.getAppointTimeStart());
		model.setAppointTimeEnd(orderParam.getAppointTimeEnd());
		model.setCreateTime(TimeUtil.timestamp());
		model.setUpdateTime(TimeUtil.timestamp());
		model.setCancelTime(TimeUtil.timestamp() + (60L * Integer.parseInt(cancelUnpaidOrdersTimes)));
		// 如果有推荐人，则优惠对应的价格
		QueryWrapper<UserSalesman> userSalesmanQueryWrapper = new QueryWrapper<>();
		userSalesmanQueryWrapper.eq("user_id", orderParam.getUserId());
		userSalesmanQueryWrapper.eq("is_delete", 0);
		UserSalesman one = userSalesmanService.getOne(userSalesmanQueryWrapper);
		SalesmanGoogs salesmanGoogs = salesmanGoogsMapper.selectOne(new LambdaQueryWrapper<SalesmanGoogs>()
				.eq(SalesmanGoogs::getSalesmanId, one.getSalesmanId())
				.eq(SalesmanGoogs::getProductId, goods.getId()));
		if (Objects.nonNull(salesmanGoogs)){
			goods.setPrice(salesmanGoogs.getProductPrice());
		}
		BigDecimal multiply = FormulaUtil.multiply(goods.getPrice(), orderParam.getTotalNum(), FormulaUtil.SCALE_TWO);
		BigDecimal discount = null;
		if(orderParam.getScanUserId() != null) {
			model.setSalesmanUserId(orderParam.getScanUserId());
			model.setIsFinish(1);
		} else {
			if(Objects.nonNull(one)) {
				Salesman salesman = salesmanMapper.selectById(one.getSalesmanId());
				discount = multiply.multiply(salesman.getDiscount().multiply(new BigDecimal("0.1")));
				model.setOrderAmount(discount);
				model.setSalesmanUserId(salesman.getUserId());
			} else {
				discount = multiply;
			}
		}
		model.setOrderAmount(discount);
		model.setTotalAmount(multiply);
		// 如果是包年服务，则将orderType设置为2
		if(Objects.nonNull(goods.getIsManualDispatch()) && goods.getIsManualDispatch().equals(GlobalConstant.DELETE)){
			model.setOrderType(GlobalConstant.TWO);
		}
		// 设置优惠券
		if (Objects.nonNull(orderParam.getCouponId())) {
			orderParam.getCouponId().forEach(item -> {
				Coupon coupon = couponMapper.selectById(item);
				if(coupon.getEndTime() - TimeUtil.timestamp() <= 0) {
					throw new OperateException("优惠券过期，不能使用");
				}
				BigDecimal amount = coupon.getAmount();
				BigDecimal subtract = model.getOrderAmount().subtract(amount);
				if(subtract.compareTo(new BigDecimal("0")) <= 0) {
					model.setOrderAmount(new BigDecimal("0"));
				} else {
					model.setOrderAmount(subtract);
				}
			});
			model.setCouponId(orderParam.getCouponId().toString());
		}
		// 判断是否是团购订单
		if(Objects.nonNull(orderParam.getIsBuy()) && orderParam.getIsBuy() == 1) {
			model.setIsBuy(orderParam.getIsBuy());
		}
		if (orderParam.getIsGratis() != null && orderParam.getIsGratis() == 1) {
			model.setOrderAmount(new BigDecimal("0"));
		}
		orderMapper.insert(model);
		Long orderId = model.getId();
		if(Objects.nonNull(orderParam.getIsBuy()) && orderParam.getIsBuy() == 1) {
			if(Objects.nonNull(orderParam.getOrderId()) && orderParam.getOrderId() != 0) {
				OrderBuyRelevancy orderBuyRelevancy = orderBuyRelevancyMapper.selectOne(new LambdaQueryWrapper<OrderBuyRelevancy>()
						.eq(OrderBuyRelevancy::getIsDelete, GlobalConstant.NOT_DELETE)
						.eq(OrderBuyRelevancy::getInitiatorOrderId, orderParam.getOrderId()));
				String relevancyOrderIds = orderBuyRelevancy.getRelevancyOrderIds();
				Integer endTime = orderBuyRelevancy.getEndTime();
				if(TimeUtil.timestamp() > endTime) {
					throw new OperateException("你拼团的订单已经过期,请重新下单一个新的订单");
				}
				String[] split = new String[0];
				if(StringUtil.isNotEmpty(relevancyOrderIds)) {
					split = relevancyOrderIds.split(",");
				}

				if(split.length+1 > goods.getBuyPeopleNum()) {
					throw new OperateException("该拼团链接的人数已满，请重新拼团！");
				}
				orderBuyRelevancy.setUnpaidOrderIds(orderBuyRelevancy.getUnpaidOrderIds() + "," + orderId);
				orderBuyRelevancyMapper.updateById(orderBuyRelevancy);
			} else {
				// 该用户首次发起团购订单
				OrderBuyRelevancy orderBuyRelevancy = new OrderBuyRelevancy();
				orderBuyRelevancy.setIsDelete(GlobalConstant.NOT_DELETE);
				orderBuyRelevancy.setBuyStatus(0);
				orderBuyRelevancy.setInitiatorOrderId(Math.toIntExact(orderId));
				orderBuyRelevancy.setCreateTime(TimeUtil.timestamp());
				orderBuyRelevancy.setBuyStatus(0);
				orderBuyRelevancy.setUnpaidOrderIds(orderId + "");
				orderBuyRelevancy.setEndTime(TimeUtil.timestamp().intValue()+goods.getBuyStartTime());
				orderBuyRelevancyMapper.insert(orderBuyRelevancy);
			}
		}
		extracted(orderParam.getTotalNum(), goods, goodsUnit.getName(), discount, orderId);
		return model;
	}

	/**
	 *
	 * @param totalNum  购买数量
	 * @param goods     商品
	 * @param goodsUnitName 规格名称
	 * @param discount      实付金额
	 * @param orderId       订单ID
	 */
	private void extracted(Integer totalNum, Goods goods, String goodsUnitName, BigDecimal discount, Long orderId) {
		// 保存订单服务信息
		OrderGoods orderGoods = new OrderGoods();
		orderGoods.setOrderId(orderId);
		orderGoods.setGoodsId(goods.getId());
		orderGoods.setGoodsName(goods.getName());
		orderGoods.setUnitName(goodsUnitName);
		orderGoods.setGoodsNum(totalNum);
		orderGoods.setGoodsPrice(goods.getPrice());
		orderGoods.setTotalPrice(FormulaUtil.multiply(goods.getPrice(), totalNum, FormulaUtil.SCALE_TWO));
		orderGoods.setTotalPayPrice(discount);
		orderGoods.setIsComment(GoodsCommentStatusEnum.WAIT_REPLY.getStatus());
		orderGoods.setGoodsSnap(goods.getContent());
		orderGoods.setCreateTime(TimeUtil.timestamp());
		orderGoods.setUpdateTime(TimeUtil.timestamp());
		orderGoodsService.insert(orderGoods);
	}


	@Override
	public Order update(OrderParam orderParam) {
		Order order = orderMapper.selectById(orderParam.getId());
		order.setAppointTimeStart(orderParam.getAppointTimeStart());
		order.setAppointTimeEnd(orderParam.getAppointTimeEnd());
		order.setOrderStatus(orderParam.getOrderStatus());
		orderMapper.updateById(order);
		return order;
	}

	/**
	 * @return com.mdd.common.entity.staff.Staff
	 * @Author slien
	 * @Description 根据城市, 预约时间 随机选择一位师傅
	 * @Date 17:37 2022/10/10
	 * @Param [orderParam]
	 **/
	private Staff getRandomStaff(OrderParam orderParam) {
		List<Staff> list = staffService.listStaff(orderParam.getGoodsId(), orderParam.getCityId());
		if (CollectionUtils.isEmpty(list)) {
			return null;
		}
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.ge(Order::getAppointTimeStart, orderParam.getAppointTimeStart());
		lambdaQueryWrapper.le(Order::getAppointTimeEnd, orderParam.getAppointTimeEnd());
		lambdaQueryWrapper.eq(Order::getCityId, orderParam.getCityId());
		List<Order> orderList = super.list(lambdaQueryWrapper);
		if (CollectionUtils.isEmpty(orderList)) {
			int random = RandomUtils.nextInt(0, list.size());
			return list.get(random);

		}
		List<Long> orderStaffIds = orderList.stream().map(Order::getStaffId).distinct().collect(Collectors.toList());
		Iterator<Staff> iterator = list.iterator();
		while (iterator.hasNext()) {
			Staff next = iterator.next();
			if (orderStaffIds.contains(next.getId())) {
				iterator.remove();
			}
		}
		if (CollectionUtils.isEmpty(list)) {
			return null;
		}
		return list.get(RandomUtils.nextInt(0, list.size()));
	}

	/**
	 * @return com.mdd.front.vo.order.OrderCancelPayVo
	 * @Author slien
	 * @Description 用户客户端手动取消订单 金额退还给用户  TODO
	 * @Date 09:02 2022/10/11
	 * @Param [id]
	 **/
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancelOrder(Long id, Long userId, Integer source) throws Exception {
		Order model = orderMapper.selectOne(
				new QueryWrapper<Order>()
						.eq("id", id)
						.eq("user_id", userId)
						.last("limit 1"));
		Assert.notNull(model, "数据不存在!");
		// 待支付 直接取消订单
		if (OrderStatusEnum.WAIT_PAY.getStatus() == model.getOrderStatus()) {
			model.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
			model.setCancelTime(TimeUtil.timestamp());
			model.setUpdateTime(TimeUtil.timestamp());
			orderMapper.updateById(model);
			this.saveOrderLog(model.getId(), model.getUserId(), OrderLogEnum.USER_CANCEL_ORDER.getDesc());
			return;
		}

		// 只有预约中的状态 用户才可以进行订单的取消
		if (OrderStatusEnum.RESERVE.getStatus() != model.getOrderStatus()) {
			throw new OperateException("只有预约中的订单才可以取消订单");
		}

		//this.wxRefund(model, userId, source);
		// 退款单创建
		OrderRefundParam param = new OrderRefundParam();
		param.setOrderId(model.getId());
		param.setUserId(model.getUserId());
		param.setType(RefundOperateEnum.TYPE_USER.getType());//用户退款
		param.setOrderTerminal(ClientEnum.MNP.getCode());
		param.setTransactionId("");
		param.setSn(SnUtils.getRefundOrderSn());
		param.setOrderAmount(model.getOrderAmount());
		param.setRefundAmount(model.getOrderAmount());
		param.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
		OrderRefund orderRefund = orderRefundService.add(param);

		// 修改订单状态
		model.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
		model.setCancelTime(TimeUtil.timestamp());
		orderMapper.updateById(model);
		// 微信退款
		//orderRefundService.checkRefundStatus();

		switch (model.getPayWay()) {
			case 1:
				WxPayRefundV3Request request = new WxPayRefundV3Request();
				request.setOutTradeNo(model.getSn());
				request.setOutRefundNo(orderRefund.getSn());
				request.setNotifyUrl(UrlUtil.localDomain(orderRefundNotifyUrl));
				WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
				amount.setCurrency("CNY");
				amount.setRefund(AmountUtil.yuan2Fen(model.getOrderAmount()));
				amount.setTotal(AmountUtil.yuan2Fen(model.getOrderAmount()));
				request.setAmount(amount);
				WxPayServiceUtils.wxPayService(model.getPayChannel()).refundV3(request);
				break;
			case 2:
				User user = userMapper.selectOne(new QueryWrapper<User>()
						.eq("id", model.getUserId())
						.eq("is_delete", 0)
						.last("limit 1"));
				Assert.notNull(user, "找不到订单所属用户！");
				user.setMoney(user.getMoney().add(model.getOrderAmount()));
				user.setUpdateTime(System.currentTimeMillis() / 1000);
				userMapper.updateById(user);
				// 添加余额明细日志
				AccountLog accountLog = new AccountLog();
				accountLog.setUserId(model.getUserId());
				accountLog.setAssociationSn(model.getSn());
				accountLog.setAction(AccountChangeEnum.ACTION_INC.getCode());
				accountLog.setChangeType(AccountEnum.UM_INC_Wallet.getCode());
				accountLog.setLeftAmount(user.getMoney());
				accountLog.setChangeAmount(model.getOrderAmount());
				accountLog.setCreateTime(System.currentTimeMillis() / 1000);
				accountLog.setUpdateTime(System.currentTimeMillis() / 1000);
				accountLogMapper.insert(accountLog);
				//插入退款日志
				OrderRefundLog orderRefundLog = new OrderRefundLog();
				orderRefundLog.setSn(orderRefund.getSn());
				orderRefundLog.setRefundId(orderRefund.getId());
				orderRefundLog.setType(OperateEnum.TYPE_SYSTEM.getType());
				orderRefundLog.setOperatorId(1L);
				orderRefundLog.setRefundAmount(orderRefund.getRefundAmount());
				orderRefundLog.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
				orderRefundLog.setWechatRefundId("");
				orderRefundLog.setRefundMsg("退款成功");
				orderRefundLog.setCreateTime(TimeUtil.timestamp());
				orderRefundLog.setUpdateTime(TimeUtil.timestamp());
				orderRefundLogService.saveEntity(orderRefundLog);
				// 更新退款信息
				orderRefund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
				orderRefundMapper.updateById(orderRefund);
				break;
			case 3:
				// 支付宝退款
				//AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, AlipayConfig.APP_ID, AlipayConfig.MERCHANT_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGN_TYPE);
				AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, ConfigUtil.getAliDevPay("app_id"), ConfigUtil.getAliDevPay("private_key"), "json", AlipayConfig.CHARSET, ConfigUtil.getAliDevPay("ali_public_key"), AlipayConfig.SIGN_TYPE);

				AlipayTradeRefundRequest aliRequest = new AlipayTradeRefundRequest();
				AlipayTradeRefundModel alipayTradeRefundModel = new AlipayTradeRefundModel();
				alipayTradeRefundModel.setTradeNo(model.getTransactionId());
				alipayTradeRefundModel.setRefundAmount(model.getOrderAmount().toString());
				alipayTradeRefundModel.setOutRequestNo(model.getSn());
				aliRequest.setBizModel(alipayTradeRefundModel);
				AlipayTradeRefundResponse response = alipayClient.execute(aliRequest);

				if (response.isSuccess()) {
					orderRefund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
					orderRefund.setRefundWay(PaymentEnum.ALI_PAY.getCode());
					orderRefund.setRefundTime(TimeUtil.timestamp());
					orderRefundMapper.updateById(orderRefund);

					//插入退款日志
					OrderRefundLog orderRefundLogAli = new OrderRefundLog();
					orderRefundLogAli.setSn(orderRefund.getSn());
					orderRefundLogAli.setRefundId(orderRefund.getId());
					orderRefundLogAli.setType(OperateEnum.TYPE_USER.getType());
					orderRefundLogAli.setOperatorId(1L);
					orderRefundLogAli.setRefundAmount(orderRefund.getRefundAmount());
					orderRefundLogAli.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
					orderRefundLogAli.setWechatRefundId("");
					orderRefundLogAli.setRefundMsg("退款成功");
					orderRefundLogAli.setCreateTime(TimeUtil.timestamp());
					orderRefundLogAli.setUpdateTime(TimeUtil.timestamp());
					orderRefundLogService.saveEntity(orderRefundLogAli);
					//System.out.println("调用支付宝退款成功");
				} else {
					throw new OperateException("调用支付宝退款失败");
				}

		}
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancelOrder(Long id, Long userId, Integer source, String returnNumber) throws Exception {
		Order model = orderMapper.selectOne(
				new QueryWrapper<Order>()
						.eq("id", id)
						.eq("user_id", userId)
						.last("limit 1"));
		Assert.notNull(model, "数据不存在!");
		// 待支付 直接取消订单
		if (OrderStatusEnum.WAIT_PAY.getStatus() == model.getOrderStatus()) {
			model.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
			model.setCancelTime(TimeUtil.timestamp());
			model.setUpdateTime(TimeUtil.timestamp());
			orderMapper.updateById(model);
			this.saveOrderLog(model.getId(), model.getUserId(), OrderLogEnum.USER_CANCEL_ORDER.getDesc());
			return;
		}

		// 只有预约中的状态 用户才可以进行订单的取消
		if (OrderStatusEnum.RESERVE.getStatus() != model.getOrderStatus()) {
			throw new OperateException("只有预约中的订单才可以取消订单");
		}
//		if (Objects.nonNull(model.getIsBuy()) && model.getIsBuy() == 1) {
//			throw new OperateException("拼团订单不能取消，如要取消请联系客服");
//		}
		//this.wxRefund(model, userId, source);
		// 退款单创建
		OrderRefundParam param = new OrderRefundParam();
		param.setOrderId(model.getId());
		param.setUserId(model.getUserId());
		param.setType(RefundOperateEnum.TYPE_USER.getType());//用户退款
		param.setOrderTerminal(ClientEnum.MNP.getCode());
		param.setSn(returnNumber);
		param.setOrderAmount(model.getOrderAmount());
		param.setRefundAmount(model.getOrderAmount());
		param.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
		param.setTransactionId(model.getTransactionId());
		OrderRefund orderRefund = orderRefundService.add(param);

		// 修改订单状态
		model.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
		model.setCancelTime(TimeUtil.timestamp());
		// 微信退款
		//orderRefundService.checkRefundStatus();

		switch (model.getPayWay()) {
			case 1:
//                WxPayRefundV3Request request = new WxPayRefundV3Request();
//                request.setOutTradeNo(model.getSn());
//                request.setOutRefundNo(orderRefund.getSn());
//                request.setNotifyUrl(UrlUtil.localDomain(orderRefundNotifyUrl));
//                WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
//                amount.setCurrency("CNY");
//                amount.setRefund(AmountUtil.yuan2Fen(model.getOrderAmount()));
//                amount.setTotal(AmountUtil.yuan2Fen(model.getOrderAmount()));
//                request.setAmount(amount);
//                WxPayServiceUtils.wxPayService(model.getPayChannel()).refundV3(request);
				//插入退款日志
				iCBCService.refund(orderRefund, userId);

				orderRefundService.update(new LambdaUpdateWrapper<OrderRefund>()
						.eq(OrderRefund::getOrderId, orderRefund.getOrderId())
						.set(OrderRefund::getRefundStatus, OrderRefundStatusEnum.SUCCESS.getStatus()));

				OrderRefundLog orderRefundLogAli2 = new OrderRefundLog();
				orderRefundLogAli2.setSn(orderRefund.getSn());
				orderRefundLogAli2.setRefundId(orderRefund.getId());
				orderRefundLogAli2.setType(OperateEnum.TYPE_USER.getType());
				orderRefundLogAli2.setOperatorId(1L);
				orderRefundLogAli2.setRefundAmount(orderRefund.getRefundAmount());
				orderRefundLogAli2.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
				orderRefundLogAli2.setWechatRefundId("");
				orderRefundLogAli2.setRefundMsg("退款成功");
				orderRefundLogAli2.setCreateTime(TimeUtil.timestamp());
				orderRefundLogAli2.setUpdateTime(TimeUtil.timestamp());
				orderRefundLogService.saveEntity(orderRefundLogAli2);
				break;
			case 2:
				User user = userMapper.selectOne(new QueryWrapper<User>()
						.eq("id", model.getUserId())
						.eq("is_delete", 0)
						.last("limit 1"));
				Assert.notNull(user, "找不到订单所属用户！");
				user.setMoney(user.getMoney().add(model.getOrderAmount()));
				user.setUpdateTime(System.currentTimeMillis() / 1000);
				userMapper.updateById(user);
				// 添加余额明细日志
				AccountLog accountLog = new AccountLog();
				accountLog.setUserId(model.getUserId());
				accountLog.setAssociationSn(model.getSn());
				accountLog.setAction(AccountChangeEnum.ACTION_INC.getCode());
				accountLog.setChangeType(AccountEnum.UM_INC_Wallet.getCode());
				accountLog.setLeftAmount(user.getMoney());
				accountLog.setChangeAmount(model.getOrderAmount());
				accountLog.setCreateTime(System.currentTimeMillis() / 1000);
				accountLog.setUpdateTime(System.currentTimeMillis() / 1000);
				accountLogMapper.insert(accountLog);
				//插入退款日志
				OrderRefundLog orderRefundLog = new OrderRefundLog();
				orderRefundLog.setSn(orderRefund.getSn());
				orderRefundLog.setRefundId(orderRefund.getId());
				orderRefundLog.setType(OperateEnum.TYPE_SYSTEM.getType());
				orderRefundLog.setOperatorId(1L);
				orderRefundLog.setRefundAmount(orderRefund.getRefundAmount());
				orderRefundLog.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
				orderRefundLog.setWechatRefundId("");
				orderRefundLog.setRefundMsg("退款成功");
				orderRefundLog.setCreateTime(TimeUtil.timestamp());
				orderRefundLog.setUpdateTime(TimeUtil.timestamp());
				orderRefundLogService.saveEntity(orderRefundLog);
				// 更新退款信息
				orderRefund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
				orderRefundMapper.updateById(orderRefund);
				break;
			case 3:
				// 支付宝退款
				//AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, AlipayConfig.APP_ID, AlipayConfig.MERCHANT_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGN_TYPE);
				AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, ConfigUtil.getAliDevPay("app_id"), ConfigUtil.getAliDevPay("private_key"), "json", AlipayConfig.CHARSET, ConfigUtil.getAliDevPay("ali_public_key"), AlipayConfig.SIGN_TYPE);

				AlipayTradeRefundRequest aliRequest = new AlipayTradeRefundRequest();
				AlipayTradeRefundModel alipayTradeRefundModel = new AlipayTradeRefundModel();
				alipayTradeRefundModel.setTradeNo(model.getTransactionId());
				alipayTradeRefundModel.setRefundAmount(model.getOrderAmount().toString());
				alipayTradeRefundModel.setOutRequestNo(model.getSn());
				aliRequest.setBizModel(alipayTradeRefundModel);
				AlipayTradeRefundResponse response = alipayClient.execute(aliRequest);

				if (response.isSuccess()) {
					orderRefund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
					orderRefund.setRefundWay(PaymentEnum.ALI_PAY.getCode());
					orderRefund.setRefundTime(TimeUtil.timestamp());
					orderRefundMapper.updateById(orderRefund);

					//插入退款日志
					OrderRefundLog orderRefundLogAli = new OrderRefundLog();
					orderRefundLogAli.setSn(orderRefund.getSn());
					orderRefundLogAli.setRefundId(orderRefund.getId());
					orderRefundLogAli.setType(OperateEnum.TYPE_USER.getType());
					orderRefundLogAli.setOperatorId(1L);
					orderRefundLogAli.setRefundAmount(orderRefund.getRefundAmount());
					orderRefundLogAli.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
					orderRefundLogAli.setWechatRefundId("");
					orderRefundLogAli.setRefundMsg("退款成功");
					orderRefundLogAli.setCreateTime(TimeUtil.timestamp());
					orderRefundLogAli.setUpdateTime(TimeUtil.timestamp());
					orderRefundLogService.saveEntity(orderRefundLogAli);
					//System.out.println("调用支付宝退款成功");
				} else {
					throw new OperateException("调用支付宝退款失败");
				}

		}
		orderMapper.updateById(model);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancelOrder(String sn, Long userId, Integer source) throws Exception {
		Order model = orderMapper.selectOne(
				new QueryWrapper<Order>()
						.eq("sn", sn)
						.last("limit 1"));
		Assert.notNull(model, "数据不存在!");
		// 待支付 直接取消订单
		if (OrderStatusEnum.WAIT_PAY.getStatus() == model.getOrderStatus()) {
			model.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
			model.setCancelTime(TimeUtil.timestamp());
			model.setUpdateTime(TimeUtil.timestamp());
			orderMapper.updateById(model);
			this.saveOrderLog(model.getId(), model.getUserId(), OrderLogEnum.USER_CANCEL_ORDER.getDesc());
			return;
		}

		// 只有预约中的状态 用户才可以进行订单的取消
		if (OrderStatusEnum.RESERVE.getStatus() != model.getOrderStatus()) {
			throw new OperateException("只有预约中的订单才可以取消订单");
		}
		// 调微信取消支付
		//this.wxRefund(model, userId, source);
	}

	@Override
	public void confirmGoods(Long id, Long userId) {
		Order model = orderMapper.selectOne(
				new QueryWrapper<Order>()
						.eq("id", id)
						.last("limit 1"));
		Assert.notNull(model, "数据不存在!");
		if (OrderStatusEnum.RESERVE.getStatus() != model.getOrderStatus()) {
			throw new OperateException("只有预约中的服务,师傅才可以确认服务");
		}
		Staff staff = staffService.getByUserId(userId);
		if (staff == null) {
			throw new OperateException("当前用户不是师傅,无法确认服务");
		}
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.ge(Order::getAppointTimeStart, model.getAppointTimeStart());
		lambdaQueryWrapper.le(Order::getAppointTimeEnd, model.getAppointTimeEnd());
		lambdaQueryWrapper.eq(Order::getStaffId, staff.getId());
		lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.SERVICING.getStatus());
		lambdaQueryWrapper.last("limit 1");
		Order order = super.getOne(lambdaQueryWrapper);
		if (order != null) {
			throw new OperateException("该预约时间段内,存在时间冲突,不能确认该服务");
		}
		// 设置为已派单说明师傅抢到订单
		model.setStaffId(staff.getId());
		model.setOrderStatus(OrderStatusEnum.SERVICING.getStatus());
		model.setIsDispatch(OrderDispatchEnum.IS_DISPATCH.getStatus());
		model.setVerificationStatus(OrderVerificationStatusEnum.WAIT_VERIFICATION.getStatus());
		model.setVerificationCode(SnUtils.get6RandomCode());
		model.setUpdateTime(TimeUtil.timestamp());
		orderMapper.updateById(model);
		this.saveOrderLog(model.getId(), staff.getUserId(), OrderLogEnum.USER_STAFF_CONFIRM.getDesc());

		// 发送通知 (师傅确认)
		try {
			Map<String, String> config = new LinkedHashMap<>();
			config.put("scene", String.valueOf(NoticeEnum.U_WORKER_CONFIRM.getCode()));
			config.put("mobile", model.getMobile());

			Map<String, String> params = new LinkedHashMap<>();
			params.put("user_name", model.getContact());
			params.put("order_sn", model.getSn());
			(new NoticeDriver()).handle(config, params);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	@Override
	public void verificationOrder(Long id, Integer userId, String code) {
		Order model = orderMapper.selectOne(
				new QueryWrapper<Order>()
						.eq("id", id)
						.last("limit 1"));
		Assert.notNull(model, "数据不存在!");
		if (OrderStatusEnum.SERVICING.getStatus() != model.getOrderStatus()) {
			throw new OperateException("只有服务中的订单才能进行核销");
		}
		if (isEnableCode) {
			String verificationCode = model.getVerificationCode();
			if (!verificationCode.equalsIgnoreCase(code)) {
				throw new OperateException("核销码错误,请重新输入");
			}
		}
		model.setVerificationStatus(OrderVerificationStatusEnum.VERIFICATION.getStatus());
		model.setOrderStatus(OrderStatusEnum.FINISHED.getStatus());
		model.setFinishTime(TimeUtil.timestamp());
		model.setUpdateTime(TimeUtil.timestamp());
		orderMapper.updateById(model);
		this.saveOrderLog(id, userId.longValue(), OrderLogEnum.USER_VERIFICATION.getDesc());

		// 发送通知 (师傅核销)
		try {
			Map<String, String> config = new LinkedHashMap<>();
			config.put("scene", String.valueOf(NoticeEnum.U_ORDER_COMPLETE.getCode()));
			config.put("mobile", model.getMobile());

			Map<String, String> params = new LinkedHashMap<>();
			params.put("user_name", model.getContact());
			params.put("order_sn", model.getSn());
			(new NoticeDriver()).handle(config, params);
		} catch (Exception e) {
			log.error("师傅核销订单失败：{}", e.getMessage());
		}
	}

	private void saveOrderLog(Long orderId, Long userId, String context) {
		OrderLog orderLog = new OrderLog();
		orderLog.setType(OperateEnum.TYPE_USER.getType());
		//orderLog.setChannel(0);
		orderLog.setOrderId(orderId);
		orderLog.setOperatorId(userId);
		orderLog.setContent(context);
		orderLog.setCreateTime(TimeUtil.timestamp());
		orderLog.setUpdateTime(TimeUtil.timestamp());
		orderLogService.saveEntity(orderLog);
	}

	@Override
	public List<Order> getNoPayOrderByDuration(int minutes) {
		LocalDateTime localDateTime = LocalDateTime.now();
		LocalDateTime time = localDateTime.minusMinutes(minutes);
		long createTime = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000;
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Order::getPayStatus, OrderPayStatusEnum.WAIT_PAY.getStatus());
		lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.WAIT_PAY.getStatus());
		lambdaQueryWrapper.le(Order::getCreateTime, createTime);
		List<Order> orderInfoList = super.list(lambdaQueryWrapper);
		return orderInfoList;
	}

	@Override
	public void checkOrderStatus(Long orderId) throws Exception {
		log.warn("根据订单号核实订单状态 ===> {}", orderId);
		//调用微信支付查单接口
		Order model = orderMapper.selectOne(
				new QueryWrapper<Order>()
						.eq("id", orderId)
						.last("limit 1"));
	}

	@Override
	public List<Order> listFinishByUserId(Long userId) {
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Order::getUserId, userId);
		lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.FINISHED.getStatus());
		List<Order> list = super.list(lambdaQueryWrapper);
		if (CollectionUtils.isEmpty(list)) {
			return Lists.newArrayList();
		}
		return list;
	}

	@Override
	public Order getById(Long orderId, Integer userId) {
		Order order = orderMapper.selectOne(new QueryWrapper<Order>()
				.eq("id", orderId)
				.eq("is_delete", 0)
				.eq("user_id", userId)
				.last("limit 1"));
		Assert.notNull(order, "数据不存在");
		return order;
	}

	@Override
	public void del(Long id) {
		Order model = orderMapper.selectOne(
				new QueryWrapper<Order>()
						.eq("id", id)
						.last("limit 1"));

		Assert.notNull(model, "数据不存在");
		if (OrderStatusEnum.CLOSE.getStatus() != model.getOrderStatus()) {
			throw new OperateException("订单为非关闭状态,不能删除");
		}
		model.setIsDelete(1);
		model.setDeleteTime(TimeUtil.timestamp());
		orderMapper.updateById(model);
	}

	@Override
	public Order updateSn(Integer id, String payChannel) {
		Order order = orderMapper.selectById(id);
		org.springframework.util.Assert.notNull(order, "订单不存在");
		order.setSn(SnUtils.getOrderSn());
		order.setPayChannel(payChannel);
		order.setPayWay(OrderPlayTypeEnum.WECHAT_PAY.getType());
		this.orderMapper.updateById(order);
		return order;
	}

	@Override
	public boolean updateOrderStatusToPaid(String outTradeNo, String transactionId) throws WxPayException {
		//处理重复的通知
		//接口调用的幂等性：无论接口被调用多少次，产生的结果是一致的。
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Order::getSn, outTradeNo);
		lambdaQueryWrapper.last("limit 1");
		Order order = super.getOne(lambdaQueryWrapper);
		Assert.notNull(order, "订单未关联到对应的订单");
		Integer payStatus = order.getPayStatus();
		if (OrderPayStatusEnum.WAIT_PAY.getStatus() != payStatus) {
			return true;
		}
		WxPayOrderQueryV3Result wxPayOrderQueryV3Result = WxPayServiceUtils.wxPayService(order.getPayChannel()).queryOrderV3(transactionId, outTradeNo);
		String tradeState = wxPayOrderQueryV3Result.getTradeState();
		transactionId = wxPayOrderQueryV3Result.getTransactionId();
		if ("SUCCESS".equals(tradeState)) {
			order.setTransactionId(transactionId);
			//更新订单状态
			order.setOrderStatus(OrderStatusEnum.RESERVE.getStatus());
			order.setPayStatus(OrderPayStatusEnum.PAY.getStatus());
			order.setPayTime(TimeUtil.timestamp());
			order.setPayWay(OrderPlayTypeEnum.WECHAT_PAY.getType());
			order.setUpdateTime(TimeUtil.timestamp());
			orderMapper.updateById(order);
			//记录支付日志
			this.saveOrderLog(order.getId(), order.getUserId(), OrderLogEnum.USER_PAY_ORDER.getDesc());

			//发送通知 (支付成功通知: 用户)
			String sn = order.getSn();
			try {
				Map<String, String> config = new LinkedHashMap<>();
				config.put("scene", String.valueOf(NoticeEnum.U_ORDER_PAY.getCode()));
				config.put("mobile", order.getMobile().trim());

				Map<String, String> params = new LinkedHashMap<>();
				params.put("user_name", order.getContact());
				String firstFourChars = sn.substring(0, 6); // 获取前四个字符
				String lastFourChars = sn.substring(sn.length() - 6); // 获取后四个字符
				params.put("order_sn1", firstFourChars);
				params.put("order_sn2", lastFourChars);
				(new NoticeDriver()).handle(config, params);
			} catch (Exception ignored) {

			}

			// 发送通知 (支付成功通知: 平台)
			try {
				String phone = ConfigUtil.get("website", "contactPhone", "");
				if (!phone.equals("")) {
					Map<String, String> pConfig = new LinkedHashMap<>();
					pConfig.put("scene", String.valueOf(NoticeEnum.P_ORDER_PAY.getCode()));
					pConfig.put("mobile", phone);

					Map<String, String> pParams = new LinkedHashMap<>();
					pParams.put("order_sn", sn);
					(new NoticeDriver()).handle(pConfig, pParams);
				}
			} catch (Exception ignored) {
			}
			return true;
		}
		return false;
	}


	@Override
	@Transactional
	public boolean updateOrderStatusToICBC(Map<String, String> result) throws Exception {
		//处理重复的通知
		//接口调用的幂等性：无论接口被调用多少次，产生的结果是一致的。
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Order::getSn, result.get("out_trade_no"));
		lambdaQueryWrapper.last("limit 1");
		Order order = super.getOne(lambdaQueryWrapper);
		log.info("回调的查询订单是： {}", order);
		log.info("回调的查询参数是： {}", result);
		Assert.notNull(order, "订单未关联到对应的订单");
		Integer payStatus = order.getPayStatus();
		if (OrderPayStatusEnum.WAIT_PAY.getStatus() != payStatus) {
			return true;
		}

		if ("交易成功".equals(result.get("return_msg"))) {
			String[] split = order.getCouponId().substring(1, order.getCouponId().length() - 1).replaceAll(" ", "").split(",");
			if(split != null && !split[0].equals("")) {
				List<Long> collect1 = Arrays.stream(split).map(Long::parseLong).collect(Collectors.toList());
				LambdaQueryWrapper<UserCoupon> queryWrapper = new LambdaQueryWrapper<>();
				collect1.forEach(couponId -> {
					queryWrapper.eq(UserCoupon::getCouponId, couponId);
					queryWrapper.eq(UserCoupon::getUserId, order.getUserId());
					queryWrapper.eq(UserCoupon::getIsDelete, GlobalConstant.NOT_DELETE);
					UserCoupon userCoupon = userCouponMapper.selectOne(queryWrapper);
					userCoupon.setIsUsed(1);
					userCoupon.setUpdateTime(TimeUtil.timestamp());
					userCouponMapper.updateById(userCoupon);
				});
			}
			String sn = order.getSn();
			log.info("{} 订单交易成功", sn);
			// 获取ICBC的订单id， 用于进行退款
			order.setTransactionId(result.get("order_id"));
			//更新订单状态
			order.setOrderStatus(OrderStatusEnum.RESERVE.getStatus());
			order.setPayStatus(OrderPayStatusEnum.PAY.getStatus());
			order.setPayTime(TimeUtil.timestamp());
			order.setPayWay(OrderPlayTypeEnum.WECHAT_PAY.getType());
			order.setUpdateTime(TimeUtil.timestamp());
			OrderGoods byOrderId = orderGoodsService.getByOrderId(order.getId());
			Goods goods = goodsService.getEntityById(byOrderId.getGoodsId());
			// 如果是包年服务，则直接修改为服务中
			if(goods.getIsManualDispatch().equals(GlobalConstant.DELETE)){
				order.setOrderStatus(OrderStatusEnum.SERVICING.getStatus());
			}
			// 如果是线下拉新订单， 则直接将状态设置为已完成
			if(order.getIsFinish() == 1) {
				order.setOrderStatus(OrderStatusEnum.FINISHED.getStatus());
			}
			// 如果是团购订单支付成功，则进行修改团购订单表的数据
			if(order.getIsBuy() == 1) {
				log.info("该订单是团购订单: {}", order);
				OrderBuyRelevancy orderBuyRelevancy = orderBuyRelevancyMapper.selectOne(new LambdaQueryWrapper<OrderBuyRelevancy>()
						.eq(OrderBuyRelevancy::getIsDelete, GlobalConstant.NOT_DELETE)
						.like(OrderBuyRelevancy::getUnpaidOrderIds, order.getId()));
				String s = StringUtil.trimStr(orderBuyRelevancy.getUnpaidOrderIds(), order.getId() + "");
				orderBuyRelevancy.setUnpaidOrderIds(s);
				if(orderBuyRelevancy.getInitiatorOrderId() != order.getId().intValue()) {
					if(StringUtil.isEmpty(orderBuyRelevancy.getRelevancyOrderIds())) {
						orderBuyRelevancy.setRelevancyOrderIds("" + order.getId());
					} else {
						orderBuyRelevancy.setRelevancyOrderIds(orderBuyRelevancy.getRelevancyOrderIds()+","+order.getId());
					}
				}
				if(StringUtil.isNotEmpty(orderBuyRelevancy.getRelevancyOrderIds()) && orderBuyRelevancy.getRelevancyOrderIds().split(",").length+1 == goods.getBuyPeopleNum()) {
					orderBuyRelevancy.setBuyStatus(GlobalConstant.DELETE); // 设置团购成功
				}
				orderBuyRelevancyMapper.updateById(orderBuyRelevancy);
			}
			orderMapper.updateById(order);
			//记录支付日志
			this.saveOrderLog(order.getId(), order.getUserId(), OrderLogEnum.USER_PAY_ORDER.getDesc());

			//发送通知 (支付成功通知: 用户)
			try {
				Map<String, String> config = new LinkedHashMap<>();
				config.put("scene", String.valueOf(NoticeEnum.U_ORDER_PAY.getCode()));
				config.put("mobile", order.getMobile().trim());

				Map<String, String> params = new LinkedHashMap<>();
				params.put("user_name", order.getContact());
				String firstFourChars = sn.substring(0, 6); // 获取前四个字符
				String lastFourChars = sn.substring(sn.length() - 6); // 获取后四个字符
				params.put("order_sn1", firstFourChars);
				params.put("order_sn2", lastFourChars);
				(new NoticeDriver()).handle(config, params);
			} catch (Exception ignored) {

			}
			// 发送通知 (支付成功通知: 平台)
			try {
				String phone = ConfigUtil.get("website", "contactPhone", "");
				if (!phone.equals("")) {
					Map<String, String> pConfig = new LinkedHashMap<>();
					pConfig.put("scene", String.valueOf(NoticeEnum.P_ORDER_PAY.getCode()));
					pConfig.put("mobile", phone);

					Map<String, String> pParams = new LinkedHashMap<>();
					pParams.put("order_sn", sn);
					(new NoticeDriver()).handle(pConfig, pParams);
				}
			} catch (Exception ignored) {
			}

			// 推销员返利
			return true;
		}
		return false;
	}

	@Override
	public OrderGoodsDetailVo initOrder(Long userId, Integer goodsNum, Long goodsId, Integer isBuy) {
		return goodsService.detailByUserId(userId, goodsNum, goodsId,isBuy);
	}



	@Override
	public PageResult<OrderPageResultDto> listWaitComment(PageParam pageParam, Map<String, String> params) {
		Page<OrderPageResultDto> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
		OrderDto orderDto = new OrderDto();
		orderDto.setOrderStatus(OrderStatusEnum.FINISHED.getStatus());
		orderDto.setUserId(StringUtils.isEmpty(params.get("userId")) ? null : Long.valueOf(params.get("userId")));
		Page<OrderPageResultDto> resultDtoPage = orderMapper.listWaitComment(page, orderDto);
		if (resultDtoPage == null || CollectionUtils.isEmpty(resultDtoPage.getRecords())) {
			return PageResult.iPageHandle(0L, resultDtoPage.getCurrent(), resultDtoPage.getSize(), Lists.newArrayList());
		}
		for (OrderPageResultDto record : resultDtoPage.getRecords()) {
			record.setGoodsImage(UrlUtil.toAbsoluteUrl(record.getGoodsImage()));
		}
		return PageResult.iPageHandle(resultDtoPage.getTotal(), resultDtoPage.getCurrent(), resultDtoPage.getSize(), resultDtoPage.getRecords());

	}

	@Override
	public Order payStatus(Long id) throws Exception {
		Order order = super.getById(id);
		Assert.notNull(order, "订单不存在!");
		this.checkOrderStatus(id);
		return super.getById(id);
	}

	@Override
	public List<Order> getNoStaffByDuration(int minutes) {
		LocalDateTime localDateTime = LocalDateTime.now();
		LocalDateTime time = localDateTime.minusMinutes(minutes);
		long createTime = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000;
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.isNull(Order::getStaffId);
		lambdaQueryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.RESERVE.getStatus());
		lambdaQueryWrapper.le(Order::getCreateTime, createTime);
		return super.list(lambdaQueryWrapper);
	}

	@Override
	public Order getBySn(String outTradeNo) {
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Order::getSn, outTradeNo);
		lambdaQueryWrapper.last("limit 1");
		return super.getOne(lambdaQueryWrapper);
	}

	@Override
	public void updateOrderPayWay(Integer orderId, Integer payWay) {
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Order::getId, orderId);
		lambdaQueryWrapper.eq(Order::getUserId, LikeFrontThreadLocal.getUserId());
		lambdaQueryWrapper.eq(Order::getIsDelete, GlobalConstant.NOT_DELETE);
		lambdaQueryWrapper.eq(Order::getPayStatus, OrderStatusEnum.WAIT_PAY.getStatus());
		lambdaQueryWrapper.eq(Order::getPayStatus, OrderPayStatusEnum.WAIT_PAY.getStatus());
		lambdaQueryWrapper.last("limit 1");
		Order order = orderMapper.selectOne(lambdaQueryWrapper);
		Assert.notNull(order, "订单不存在或不处于待支付状态！");
		order.setPayWay(payWay);
		order.setUpdateTime(System.currentTimeMillis() / 1000);
		orderMapper.updateById(order);
	}

	@Override
	public boolean updateAliPayOrderStatusToPaid(String outTradeNo, String transactionId) {
		LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Order::getSn, outTradeNo);
		lambdaQueryWrapper.last("limit 1");
		Order order = super.getOne(lambdaQueryWrapper);

		LambdaQueryWrapper<RechargeOrder> lambdaQueryWrapperRe = new LambdaQueryWrapper<>();
		lambdaQueryWrapperRe.eq(RechargeOrder::getOrderSn, outTradeNo);
		lambdaQueryWrapperRe.last("limit 1");
		RechargeOrder rechargeOrder = rechargeOrderMapper.selectOne(lambdaQueryWrapperRe);
		if (StringUtil.isNotNull(rechargeOrder)) { //充值订单
			iRechargeService.updateAliOrderStatusToPaid(outTradeNo, transactionId);
		} else { //预约订单
			Assert.notNull(order, "订单未关联到对应的订单");
			Integer payStatus = order.getPayStatus();
			if (OrderPayStatusEnum.WAIT_PAY.getStatus() != payStatus) {
				return true;
			}

			order.setTransactionId(transactionId);
			//更新订单状态
			order.setOrderStatus(OrderStatusEnum.RESERVE.getStatus());
			order.setPayStatus(OrderPayStatusEnum.PAY.getStatus());
			order.setPayTime(TimeUtil.timestamp());
			order.setPayWay(OrderPlayTypeEnum.ALI_PAY.getType());
			order.setUpdateTime(TimeUtil.timestamp());
			orderMapper.updateById(order);
			//记录支付日志
			this.saveOrderLog(order.getId(), order.getUserId(), OrderLogEnum.USER_PAY_ORDER.getDesc());

			//发送通知 (支付成功通知: 用户)
			String sn = order.getSn();
			try {
				Map<String, String> config = new LinkedHashMap<>();
				config.put("scene", String.valueOf(NoticeEnum.U_ORDER_PAY.getCode()));
				config.put("mobile", order.getMobile().trim());

				Map<String, String> params = new LinkedHashMap<>();
				params.put("user_name", order.getContact());
				String firstFourChars = sn.substring(0, 6); // 获取前四个字符
				String lastFourChars = sn.substring(sn.length() - 6); // 获取后四个字符
				params.put("order_sn1", firstFourChars);
				params.put("order_sn2", lastFourChars);
				(new NoticeDriver()).handle(config, params);
			} catch (Exception ignored) {
			}

			// 发送通知 (支付成功通知: 平台)
			try {
				String phone = ConfigUtil.get("website", "contactPhone", "");
				if (!phone.equals("")) {
					Map<String, String> pConfig = new LinkedHashMap<>();
					pConfig.put("scene", String.valueOf(NoticeEnum.P_ORDER_PAY.getCode()));
					pConfig.put("mobile", phone);

					Map<String, String> pParams = new LinkedHashMap<>();
					pParams.put("order_sn", sn);
					(new NoticeDriver()).handle(pConfig, pParams);
				}
			} catch (Exception ignored) {
			}

		}
		return true;
	}


	@Override
	public String callUserPhone(Map<String, String> map) throws ExecutionException, InterruptedException {
		String phoneFromNumber = map.get("phoneFromNumber");
		String phoneToNumber = map.get("phoneToNumber");
		if(StringUtils.isEmpty(phoneFromNumber) || StringUtils.isEmpty(phoneToNumber)){
			throw new OperateException("参数错误");
		}
		return  AliPhoneUtil.getVirtualNumbers(phoneFromNumber, phoneToNumber);
	}

	/**
	 * @param orderId
	 * @param userId
	 * @return
	 */
	@Override
	public List<OrderListVo> getBuyOrder(Long orderId, Integer userId) {
		// 查询团购订单表
		OrderBuyRelevancy orderBuyRelevancy = new OrderBuyRelevancy();
		OrderBuyRelevancy orderBuyRelevancy1 = orderBuyRelevancyMapper.getBuyRelevancy(orderId);
		List<OrderListVo> orders = new ArrayList<>();
		if(orderBuyRelevancy1 == null) {
			orderBuyRelevancy.setInitiatorOrderId(Math.toIntExact(orderId));
		}else {
			orderBuyRelevancy = orderBuyRelevancy1;
		}


		Order order1 = orderMapper.selectById(orderBuyRelevancy.getInitiatorOrderId());
		// 查询商品
		Long goodsId = orderGoodsMapper.selectOne(new LambdaQueryWrapper<OrderGoods>().eq(OrderGoods::getOrderId, order1.getId())).getGoodsId();
		Goods goods = goodsMapper.selectById(goodsId);
		OrderListVo orderListVo = new OrderListVo();
		BeanUtil.copyProperties(order1, orderListVo);
		if(goods.getBuyPeopleNum() == null || goods.getBuyPeopleNum() <= 0) {
			orders.add(orderListVo);
			return orders;
		}
		Integer buyPeopleNum = goods.getBuyPeopleNum();
		orderListVo.setImage(userMapper.selectById(order1.getUserId()).getAvatar());
		orderListVo.setBuyPeopleNum(buyPeopleNum);
		if(orderBuyRelevancy != null && orderBuyRelevancy.getEndTime() != null) {
			Integer endTime = orderBuyRelevancy.getEndTime();
			orderListVo.setEndTime(endTime);
		}
		orders.add(orderListVo);
		// 查询用户
		if (Objects.nonNull(orderBuyRelevancy.getRelevancyOrderIds()) && !orderBuyRelevancy.getRelevancyOrderIds().isEmpty()) {
			List<Order> orders1 = this.baseMapper.selectBatchIds(Arrays.asList(orderBuyRelevancy.getRelevancyOrderIds().split(",")));
			orders1.forEach(order -> {
				OrderListVo orderListVo1 = new OrderListVo();
				BeanUtil.copyProperties(order, orderListVo1);
				orderListVo1.setImage(userMapper.selectById(order.getUserId()).getAvatar());
				orderListVo1.setBuyPeopleNum(buyPeopleNum);
				orders.add(orderListVo1);
			});
		}
		return orders;
	}

	@Override
	public Map<String, String> createBuyOrder(Integer adminId, Integer goodsId) {
		Map<String, String> hashMap =  new HashMap<>();
		Order model = new Order();
		// 订单编号
		model.setSn(SnUtils.getOrderSn());
		model.setUserId(Long.valueOf(adminId));
		// 第三方交易流水
		//model.setTransactionId(orderParam.getTransactio);
		// 选择师傅
		model.setIsDispatch(OrderDispatchEnum.IS_DISPATCH.getStatus());
		model.setOrderType(0);
		// 默认小程序
		model.setOrderTerminal(1);
		// 设置为已完成并且设置为已支付
		model.setOrderStatus(OrderStatusEnum.FINISHED.getStatus());
		model.setPayStatus(OrderPayStatusEnum.PAY.getStatus());
		// v1.0版本默认微信支付
		model.setPayWay(PaymentEnum.WALLET_PAY.getCode());
		model.setUserRemark("该订单不能退单 该订单是推销员团购发起订单");
		model.setOrderRemarks("该订单不能退单 该订单是推销员团购发起订单");
		//model.setVerificationCode(orderParam.getVerificationCode());
		// 默认未核销
		model.setVerificationStatus(OrderVerificationStatusEnum.VERIFICATION.getStatus());

		// 获取用户信息
		User user = userMapper.selectById(adminId);
		model.setContact(user.getNickname());
		model.setMobile(user.getMobile());
		model.setProvinceId(440000L);  // 设置为广东省
		model.setCityId(440300L);  // 设置为深圳市
		model.setDistrictId(440305L); // 设置为南山区
		model.setAddress("推销员团购订单地址");

		// 服务信息
		Goods goods = goodsService.getEntityById(Long.valueOf(goodsId));
		Assert.notNull(goods, "服务信息不能为空");
		// 设置订单价格为0
		model.setGoodsPrice(BigDecimal.ZERO);

		// GoodsUnit goodsUnit = unitMapper.selectById(goods.getUnitId());
		// Assert.notNull(goodsUnit, "单位信息不能为空");
		//获取订单取消时间
		Map<String, String> config = ConfigUtil.get("transaction");
		String cancelUnpaidOrdersTimes = config.getOrDefault("cancel_unpaid_orders_times", TimeUtil.timestamp() + "");
		model.setTotalAmount(BigDecimal.ZERO);
		model.setTotalNum(1);
		model.setAppointTimeStart(TimeUtil.timestamp());
		model.setAppointTimeEnd(TimeUtil.timestamp());
		model.setCreateTime(TimeUtil.timestamp());
		model.setUpdateTime(TimeUtil.timestamp());
		model.setCancelTime(TimeUtil.timestamp() + (60L * Integer.parseInt(cancelUnpaidOrdersTimes)));
		// 如果有推荐人，则优惠对应的价格
		model.setOrderAmount(BigDecimal.ZERO);
		model.setIsFinish(1);
		// 判断是否是团购订单
		model.setIsBuy(1);
		model.setIsSalesmanBuy(1);
		orderMapper.insert(model);
		model.setIsDelete(GlobalConstant.DELETE);
		hashMap.put("id", goodsId+"");
		log.info("该订单是团购订单: {}", model);
		OrderBuyRelevancy orderBuyRelevancy = new OrderBuyRelevancy();
		orderBuyRelevancy.setIsDelete(GlobalConstant.NOT_DELETE);
		orderBuyRelevancy.setBuyStatus(0);
		orderBuyRelevancy.setInitiatorOrderId(Math.toIntExact(model.getId()));
		orderBuyRelevancy.setCreateTime(TimeUtil.timestamp());
		orderBuyRelevancy.setUnpaidOrderIds(model.getId() + "");
		orderBuyRelevancy.setEndTime(2147483647);
		orderBuyRelevancyMapper.insert(orderBuyRelevancy);
		Integer userId = LikeFrontThreadLocal.getUserId();
		String userFileName = "团购码" + userId + goodsId;
		Album album1 = iAlbumService.getBaseMapper().selectOne(new LambdaQueryWrapper<Album>().like(Album::getName, userFileName).eq(Album::getIsDelete, GlobalConstant.DELETE));
		if (Objects.nonNull(album1)){
			hashMap.put("url", album1.getUri());
			return hashMap;
		}
		String fileName = userFileName +ToolsUtil.makeUUID().substring(5, 15) + ".png";
		try {
			StringBuilder sendUrl = new StringBuilder(url);
			Map<String, Object> requestBody = new HashMap<>();
			requestBody.put("page", "pages/goods/index");  // 设置二维码跳转的地址
			requestBody.put("scene", "isBuy_id=" + model.getId() + "&id=" + goodsId);  // 设置拉新人的id
			requestBody.put("width", 430);     // 设置宽度
			requestBody.put("auto_color", false);
			requestBody.put("env_version", envProfile);
			Map<String, String> color = new HashMap<>();
			color.put("r", "125");
			color.put("g", "82");
			color.put("b", "132");
			requestBody.put("line_color", color);
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<Map<String, Object>>(requestBody, headers);
			String accessTokenKey = "wx:accessToken";
			// 获取wx的accessToken，如果没有则调用接口获取
			String getAccessTokenUrl = accessTokenUrl + "?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
			String forObject = restTemplate.getForObject(getAccessTokenUrl, String.class);
			JSONObject jsonObject = JSONUtil.parseObj(forObject);
			String accessToken = jsonObject.getStr("access_token");
			sendUrl.append("?access_token=" + accessToken);
			byte[] result = restTemplate.postForObject(sendUrl.toString(), httpEntity, byte[].class);
			MultipartFile multipartFile = new MockMultipartFile(fileName, fileName, MimeTypeUtils.IMAGE_PNG_VALUE, result);
			StorageDriver storageDriver = new StorageDriver();
			Map<String, Object> map = storageDriver.upload(multipartFile, "image", AlbumEnum.IMAGE.getCode());
			Map<String, String> album = new LinkedHashMap<>();
			album.put("aid", "0");
			// 设置为66，代表拉新订单码
			album.put("cid", GlobalConstant.QR_SCAN_PAY + "");
			album.put("type", String.valueOf(AlbumEnum.IMAGE.getCode()));
			album.put("size", map.get("size").toString());
			album.put("ext", map.get("ext").toString());
			album.put("url", map.get("url").toString());
			album.put("name", map.get("name").toString());
			iAlbumService.albumAdd(album);
			hashMap.put("url", album.get("url"));
			return hashMap;
		} catch (Exception e) {
			log.error(e.toString());
		}
//		return null;
		log.error("生成团购二维码失败");
		return hashMap;
	}

}
